#ifndef __FL_TCPSOCKET_H__
#define __FL_TCPSOCKET_H__

#include "cocos2d.h"
#ifdef WIN32
#include <windows.h>
#include <WinSock.h>
#pragma comment( lib, "ws2_32.lib" )
#else
#include <sys/socket.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define SOCKET int
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1

#endif

#ifndef CHECKF
#define CHECKF(x) \
	do \
{ \
	if (!(x)) { \
	log_msg("CHECKF", #x, __FILE__, __LINE__); \
	return 0; \
	} \
} while (0)
#endif

#define _MAX_MSGSIZE 16 * 1024        
#define BLOCKSECONDS    30            
#define INBUFSIZE    (64*1024)        
#define OUTBUFSIZE    (8*1024)        

class NetworkProtocol;

class TCPSocket
{
public:
	enum SocketState
	{
		Socket_Disconnected,
		Socket_Connecting,
		Socket_Connected,
	};

public:
	TCPSocket(void);
	bool create(const char* pszServerIP, int nServerPort, int tagid, NetworkProtocol* protocol,
		int nBlockSec = BLOCKSECONDS, bool bKeepAlive = false);
	void destroy(void);
	bool polling();
	void callRemoteCommand(unsigned int cmd_id, va_list* pargs);
	SOCKET getSocket(void) const { return m_scktClient; }

	int getTagID(){ return m_tag; }

	SocketState getState() { return m_scktState; };

private:
	bool doRead();
	bool doWrite();
	bool hasError();            
	void closeSocket();

private:
	SOCKET m_scktClient;

	char m_bufOutput[OUTBUFSIZE];   
	int m_nOutbufLen;

	char m_bufInput[INBUFSIZE];
	int m_nInbufLen;
	int m_tag;

	char m_bufMakePacket[OUTBUFSIZE];
	int m_nMakePacketLen;

	SocketState m_scktState;
	NetworkProtocol* m_pProtocol;
	int m_nBlockSeconds;

	unsigned char m_keyDecrypt;
	int m_idxDecodeTable;
	bool m_bFirstDecode;
	unsigned char m_keyEncrypt;
	int m_idxEncryptTable;
	bool m_bFirstEncode;
};

#endif //__CC_TCPSOCKET_H__